﻿using System;
using OpenTK;
using OpenTK.Graphics;
using OpenTK.Graphics.OpenGL4;
using OpenTK.Input;
using Painter3D.RenderSys;
using Painter3D.RenderSys.RenderObject;
using Painter3D.PhysicalSys;
using ImGuiNET;
using Painter3D.RenderSys.DebugDrawer;
using Painter3D.Tool;

namespace Painter3D
{
    class Window : GameWindow
    {
        public struct WindowConfigStruct
        {
            public int width;
            public int height;
            public Window window;
        };

        public Window(int width, int height, string title) : base(width, height, GraphicsMode.Default, title)
        {
            //WindowState = WindowState.Fullscreen;
            CursorGrabbed = true;
            windowConfig.window = this;
            windowConfig.width = Width;
            windowConfig.height = Height;

        }

        public static WindowConfigStruct windowConfig;
        Font font;
        BulletEngine bullet;
        Dear_ImGui_Sample.ImGuiController gui;


        protected override void OnUpdateFrame(FrameEventArgs e)
        {
            bullet.Update();
            InputManager.OperateInput((float)e.Time);
            Transform.WorldTransform.LoopTreeWithF((transform) =>
            {
                foreach (var component in transform.components)
                {
                    component.Update();
                }
                return false;
            });
            Tool.QuickTool.OnUpdate();
            if (InputManager.keyboard.IsKeyDown(Key.Escape))
            {
                Close();
            }
            base.OnUpdateFrame(e);
        }

        protected override void OnLoad(EventArgs e)
        {
            gui = new Dear_ImGui_Sample.ImGuiController(800, 600);
            ImGui.GetIO().ConfigFlags |= ImGuiConfigFlags.DockingEnable;
            bullet = new BulletEngine();
            InputManager.Init(this);

            GL.ClearColor(0.2f, 0.3f, 0.3f, 1.0f);

            ShaderManager.LoadDefaultShader();
            DebugDrawer.Init(100);
            UI.UI.Init();
            QuickTool.Init();

            font = new Font(@"F:\Painter3D\Resource\Font\微软雅黑xml.fnt", @"F:\Painter3D\Resource\Font\微软雅黑xml.png");

            new Transform("charUI").AddRender(font.VertexData2D("这是一个UI层的标签"), new Material(ShaderManager.Find("Font.glsl"), new object[] { "mainTexture", font.texture, "mainColor", new Vector4(1.0f, 1.0f, 1.0f, 1.0f) })).layer.SetLayer("ui");
            new Transform("char3D").AddRender(font.VertexData3D("这是一个Lable层的标签"), new Material(ShaderManager.Find("Font.glsl")).WithValue("mainTexture", font.texture).WithValue("mainColor", new Vector4(1.0f, 1.0f, 1.0f, 1.0f))).layer.SetLayer("lable");

            Transform skyBox = new Transform("SkyBox");
            skyBox.AddRender(InnerShape.Box(), new Material(ShaderManager.Find("SkyBox.glsl")).WithValue("skyBox", new TextureBox(new string[]{
                @"F:\Painter3D\Resource\Texture\SkyBox\right.jpg",
                @"F:\Painter3D\Resource\Texture\SkyBox\left.jpg",
                @"F:\Painter3D\Resource\Texture\SkyBox\top.jpg",
                @"F:\Painter3D\Resource\Texture\SkyBox\bottom.jpg",
                @"F:\Painter3D\Resource\Texture\SkyBox\back.jpg",
                @"F:\Painter3D\Resource\Texture\SkyBox\front.jpg",
            }, false, true))).layer.SetLayer("lock");

            Camera.scenceMainCamera = new CameraPerspective(45, 800, 600, new Transform("ScenceCamera"));
            Camera.uiMainCamera = new CameraOrthographic(800, 600, new Transform("UICamera"));
            Camera.scenceMainCamera.Transform.position = new Vector3(0, 0, 10);

            new Tool.FPSCameraControl(Transform.FindByPath(@"World\ScenceCamera"));

            Transform box = new Transform("Box");
            box.Translate(Vector3.UnitY * 10);
            box.AddRender(InnerShape.Box(), new Material(ShaderManager.Find("Texture.glsl")).WithValue("mainTexture", new Texture2D(@"F:\Painter3D\Resource\Texture\WoodTexture.png")));
            new RigidBody(box, new BulletSharp.BoxShape(1.0f), RigidBody.RigidBodyTypeEnum.Dynamic);

            Transform coord = new Transform("Coord", box);
            coord.AddRender(InnerShape.XYZCoord(), new Material(ShaderManager.Find("VertexColor.glsl"))).layer.SetLayer("symbol");
            new RigidBody(coord, new BulletSharp.BoxShape(new Vector3(5, 0.01f, 5).Convert2BT()), RigidBody.RigidBodyTypeEnum.Static);

            new Transform("Grid").AddRender(InnerShape.Grid(5, 1, 1), new Material(ShaderManager.Find("SolidColor.glsl")).WithValue("mainColor", new Vector4(0.4f, 0.4f, 0.4f, 1.0f)));
            new Transform("Dautum").AddRender(InnerShape.DatumLine(), new Material(ShaderManager.Find("VertexColor.glsl")));

            ModuleImporter.Load(@"F:\Painter3D\Resource\Module\Ring.stl", Assimp.PostProcessSteps.Triangulate, out float[] position, out uint[] index);
            VertexData sphereData = new ElementVertexData(position, index, BeginMode.Triangles);
            Transform import = new Transform("import");
            import.AddRender(sphereData, new Material(ShaderManager.Find("SolidColor.glsl")).WithValue("mainColor", new Vector4(1, 0, 0, 0.5f))).layer.SetLayer("transparent");
            import.position = new Vector3(3, 0, 0);

            ModuleImporter.Load(@"F:\Painter3D\Resource\Module\Cube.stl", Assimp.PostProcessSteps.Triangulate, out float[] position1, out uint[] index1, out float[] normal1);
            VertexData cubeData = new ElementVertexData(
                new ShaderInfo.VertexRequestTagEnum[] {
                    ShaderInfo.VertexRequestTagEnum.Position,
                    ShaderInfo.VertexRequestTagEnum.Normal
                }
                , new float[][] { position1, normal1 }, index1, BeginMode.Triangles); ;
            Transform importC = new Transform("LightCube");
            importC.AddRender(cubeData, new Material(ShaderManager.Find("PhongLight.glsl")).WithValue("mainColor", new Vector3(1.0f, 1.0f, 1.0f)));
            importC.position = new Vector3(-3, 0, 0);


            UniformBlock.SetValue("LightBlock", "lightColor", new Vector3(1.0f, 1.0f, 1.0f));
            UniformBlock.SetValue("LightBlock", "lightPosition", new Vector3(0.0f, 0.0f, 0.0f));

            //设置可编程管线
            new BasicRenderPiple(skyBox);
            //RenderPiple.renderPiple = FlexableRenderPiple.InnerRenderPiple();
            base.OnLoad(e);
        }

        protected override void OnUnload(EventArgs e)
        {
            bullet.Dispose();
            UniformBlock.Clear();
            ShaderManager.Clear();
            DebugDrawer.instance.Dispose();
            Transform.WorldTransform.LoopTreeWithF((transform) =>
            {
                foreach (var component in transform.components)
                {
                    component.Dispose();

                }
                return false;
            });
            base.OnUnload(e);
        }

        protected override void OnRenderFrame(FrameEventArgs e)
        {
            gui.Update(this, (float)e.Time);

            RenderPiple.renderPiple.RenderOut();

            //ImGui.Begin("BasicInformation");
            //ImGui.Text("Fps:" + (int)RenderFrequency);
            //ImGui.Text("Mouse:" + InputManager.mouse.X + ',' + InputManager.mouse.Y);
            //ImGui.Text(String.Format("MouseNormalized:{0:N3},{1:N3}", InputManager.mouse.NormalizedPosition().X, InputManager.mouse.NormalizedPosition().Y));
            //ImGui.End();

            QuickTool.OnRenderFrame();
            bullet.DebugDraw();
            DebugDrawer.instance.DrawOut();

            UI.UI.Render();
            gui.Render();

            Context.SwapBuffers();
            base.OnRenderFrame(e);
        }

        protected override void OnResize(EventArgs e)
        {
            gui.WindowResized(Width, Height);
            windowConfig.width = Width;
            windowConfig.height = Height;
            Camera.scenceMainCamera.width = Width;
            Camera.scenceMainCamera.height = Height;
            Camera.uiMainCamera.width = Width;
            Camera.uiMainCamera.height = Height;
            Camera.uiMainCamera.Transform.position = new Vector3(Width / 2, Height / 2, 10);
            base.OnResize(e);
        }

        protected override void OnKeyPress(KeyPressEventArgs e)
        {
            gui.PressChar(e.KeyChar);
            base.OnKeyPress(e);
        }
    }
}
